home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 2 / Amiga Tools 2.iso / tools / jade / src / x11_windows.c < prev    next >
C/C++ Source or Header  |  1995-03-09  |  14KB  |  527 lines

  1. /* x11_windows.c -- Window handling for X11
  2.    Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
  3.  
  4.    This file is part of Jade.
  5.  
  6.    Jade is free software; you can redistribute it and/or modify it
  7.    under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2, or (at your option)
  9.    any later version.
  10.  
  11.    Jade is distributed in the hope that it will be useful, but
  12.    WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with Jade; see the file COPYING.    If not, write to
  18.    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include "jade.h"
  21. #include "jade_protos.h"
  22. #include "revision.h"
  23.  
  24. #include <string.h>
  25. #include <X11/Xutil.h>
  26.  
  27. _PR int sys_sleep_vw(VW *);
  28. _PR int sys_unsleep_vw(VW *);
  29. _PR void sys_new_vw(VW *);
  30. _PR void sys_kill_vw(VW *);
  31. _PR void sys_update_dimensions(VW *);
  32. _PR void x11_update_dimensions(VW *, int, int);
  33. _PR Window sys_new_window(VW *, VW *, bool);
  34. _PR void sys_kill_window(VW *);
  35. _PR void sys_activate_win(VW *);
  36. _PR void sys_set_vw_pos(VW *, long, long, long, long);
  37. _PR VW *x11_find_window_view(Window);
  38. _PR int sys_set_font(VW *);
  39. _PR void sys_unset_font(VW *);
  40. _PR void sys_reset_sleep_titles(TX *);
  41. _PR bool sys_get_mouse_pos(POS *, VW *);
  42. _PR void sys_windows_init(void);
  43.  
  44. #define INPUT_EVENTS ButtonPressMask | ButtonReleaseMask | KeyPressMask \
  45.              | ExposureMask | StructureNotifyMask | FocusChangeMask
  46.  
  47. static XSizeHints size_hints;
  48. static XClassHint class_hints = { "jade", "Editor" };
  49. static XWMHints wm_hints;
  50.  
  51. /* Let the window-manager handle all iconifying... */
  52. int
  53. sys_sleep_vw(VW *vw)
  54. {
  55.     if((vw->vw_Flags & VWFF_SLEEPING) == 0)
  56.     {
  57.     XIconifyWindow(x11_display, vw->vw_Window, x11_screen);
  58.     vw->vw_Flags |= VWFF_SLEEPING;
  59.     }
  60.     return(TRUE);
  61. }
  62.  
  63. int
  64. sys_unsleep_vw(VW *vw)
  65. {
  66.     if(vw->vw_Flags & VWFF_SLEEPING)
  67.     {
  68.     /* Does this work?? */
  69.     wm_hints.flags |= StateHint;
  70.     wm_hints.initial_state = IconicState;
  71.     XSetWMHints(x11_display, vw->vw_Window, &wm_hints);
  72.     XMapWindow(x11_display, vw->vw_Window);
  73.     vw->vw_Flags &= ~VWFF_SLEEPING;
  74.     }
  75.     return(TRUE);
  76. }
  77.  
  78. void
  79. sys_new_vw(VW *vw)
  80. {
  81. }
  82.  
  83. void
  84. sys_kill_vw(VW *vw)
  85. {
  86. }
  87.  
  88. void
  89. sys_update_dimensions(VW *vw)
  90. {
  91.     XWindowAttributes xwa;
  92.     XGetWindowAttributes(x11_display, vw->vw_Window, &xwa);
  93.     x11_update_dimensions(vw, xwa.width, xwa.height);
  94. }
  95.  
  96. void
  97. x11_update_dimensions(VW *vw, int width, int height)
  98. {
  99.     if(vw->vw_Window && ((vw->vw_Flags & VWFF_SLEEPING) == 0))
  100.     {
  101.     vw->vw_MessageLineY = height - vw->vw_FontY - 2;
  102.     vw->vw_MessageFontY = vw->vw_MessageLineY + 2 + FONT_ASCENT(vw);
  103.  
  104.     vw->vw_XStartPix = 0;
  105.     vw->vw_YStartPix = 0;
  106.     /*
  107.      * only measure *text* area, not where messages go
  108.      */
  109.     vw->vw_XEndPix = width;
  110.     vw->vw_YEndPix = (vw->vw_MessageLineY - 1);
  111.     vw->vw_XWidthPix = vw->vw_XEndPix - vw->vw_XStartPix;
  112.     vw->vw_YHeightPix = vw->vw_YEndPix - vw->vw_YStartPix;
  113.  
  114.     vw->vw_FontStart = vw->vw_YStartPix + vw->vw_Font->ascent;
  115.  
  116.     vw->vw_MaxX = (vw->vw_XWidthPix / vw->vw_FontX);
  117.     vw->vw_MaxY = (vw->vw_YHeightPix / vw->vw_FontY);
  118.     if((vw->vw_XStepRatio <= 0)
  119.        || ((vw->vw_XStep = vw->vw_MaxX / vw->vw_XStepRatio) <= 0))
  120.         vw->vw_XStep = 1;
  121.     if((vw->vw_YStepRatio <= 0)
  122.        || ((vw->vw_YStep = vw->vw_MaxY / vw->vw_YStepRatio) <= 0))
  123.         vw->vw_YStep = 1;
  124.     }
  125. }
  126.  
  127. /*
  128.  * The only thing necessary in `vw' is the font stuff (I think)
  129.  */
  130. Window
  131. sys_new_window(VW *oldVW, VW *vw, bool useDefDims)
  132. {
  133.     unsigned int x, y, width, height;
  134.     Window win;
  135.     size_hints.flags = 0;
  136.     if(!useDefDims && oldVW)
  137.     {
  138.     x = y = 0;
  139.     width = vw->vw_FontX * oldVW->vw_MaxX;
  140.     height = (vw->vw_FontY * (oldVW->vw_MaxY + 1)) + 3;
  141.     size_hints.flags |= PPosition | PSize;
  142.     }
  143.     else
  144.     {
  145.     if(def_dims[0] != -1)
  146.     {
  147.         x = def_dims[0];
  148.         size_hints.flags |= USPosition;
  149.     }
  150.     else
  151.         x = 0;
  152.     if(def_dims[1] != -1)
  153.     {
  154.         y = def_dims[1];
  155.         size_hints.flags |= USPosition;
  156.     }
  157.     else
  158.         y = 0;
  159.     if(def_dims[2] != -1)
  160.     {
  161.         width = def_dims[2];
  162.         size_hints.flags |= USSize;
  163.     }
  164.     else
  165.         width = 80;
  166.     if(def_dims[3] != -1)
  167.     {
  168.         height = def_dims[3];
  169.         size_hints.flags |= USSize;
  170.     }
  171.     else
  172.         height = 24;
  173.     width = vw->vw_FontX * width;
  174.     height = (vw->vw_FontY * (height + 1)) + 3;
  175.     }
  176.     win = XCreateSimpleWindow(x11_display, DefaultRootWindow(x11_display),
  177.                   x, y, width, height,
  178.                   1, x11_fore_pixel, x11_back_pixel);
  179.     if(win)
  180.     {
  181.     XGCValues xgcv;
  182.     vw->vw_Window = win;
  183. /*
  184.  *    xgcv.plane_mask = x11_fore_pixel | x11_back_pixel;
  185.  */
  186.     xgcv.foreground = x11_fore_pixel;
  187.     xgcv.background = x11_back_pixel;
  188.     xgcv.line_width = 1;
  189.     xgcv.font = vw->vw_Font->fid;
  190.     vw->vw_WindowSys.ws_TextFontGC = XCreateGC(x11_display, vw->vw_Window,
  191.                            GCForeground | GCBackground
  192.                            | GCLineWidth | GCFont,
  193.                            &xgcv);
  194.     xgcv.foreground = x11_back_pixel;
  195.     xgcv.background = x11_fore_pixel;
  196.     vw->vw_WindowSys.ws_BlkFontGC = XCreateGC(x11_display, vw->vw_Window,
  197.                           GCForeground | GCBackground
  198.                           | GCLineWidth | GCFont,
  199.                           &xgcv);
  200.     size_hints.x = x,
  201.     size_hints.y = y,
  202.     size_hints.width = width,
  203.     size_hints.height = height,
  204.     size_hints.base_width = 0;
  205.     size_hints.base_height = vw->vw_FontY + 3;
  206.     size_hints.width_inc = vw->vw_FontX;
  207.     size_hints.height_inc = vw->vw_FontY;
  208.     size_hints.min_width = size_hints.base_width + size_hints.width_inc;
  209.     size_hints.min_height = size_hints.base_height + size_hints.height_inc;
  210.     size_hints.flags |= PMinSize | PResizeInc | PBaseSize;
  211.     wm_hints.flags = InputHint | StateHint;
  212.     wm_hints.input = True;
  213.     wm_hints.initial_state = NormalState;
  214.     XSetWMProperties(x11_display, win, NULL, NULL, x11_argv, x11_argc, &size_hints, &wm_hints, &class_hints);
  215.     XStoreName(x11_display, win, /* "jade" */ VERSSTRING);
  216.     XSetWMProtocols(x11_display, win, &x11_wm_del_win, 1);
  217.     XSelectInput(x11_display, win, INPUT_EVENTS);
  218.     XMapWindow(x11_display, win);
  219.     XDefineCursor(x11_display, win, x11_text_cursor);
  220.     return(win);
  221.     }
  222.     return(FALSE);
  223. }
  224.  
  225. void
  226. sys_kill_window(VW *vw)
  227. {
  228.     XFreeGC(x11_display, vw->vw_WindowSys.ws_BlkFontGC);
  229.     XFreeGC(x11_display, vw->vw_WindowSys.ws_TextFontGC);
  230.     XDestroyWindow(x11_display, vw->vw_Window);
  231. }
  232.  
  233. void
  234. sys_activate_win(VW *vw)
  235. {
  236.     /* Not sure about all this??  */
  237.     XRaiseWindow(x11_display, vw->vw_Window);
  238.     XWarpPointer(x11_display, None, vw->vw_Window, 0, 0, 0, 0, 1, 1);
  239. }
  240.  
  241. void
  242. sys_set_vw_pos(VW *vw, long x, long y, long w, long h)
  243. {
  244.     XMoveResizeWindow(x11_display, vw->vw_Window,
  245.               (unsigned int)x, (unsigned int)y,
  246.               (unsigned int)w, (unsigned int)h);
  247. }
  248.  
  249. VW *
  250. x11_find_window_view(Window win)
  251. {
  252.     VW *vw = view_chain;
  253.     while(vw)
  254.     {
  255.     if(vw->vw_Window == win)
  256.         break;
  257.     vw = vw->vw_Next;
  258.     }
  259.     return(vw);
  260. }
  261.  
  262. int
  263. sys_set_font(VW *vw)
  264. {
  265.     XFontStruct *font;
  266.     if((font = XLoadQueryFont(x11_display, VSTR(vw->vw_FontName)))
  267.        || (font = XLoadQueryFont(x11_display, DEFAULT_FONT)))
  268.     {
  269.     if(vw->vw_Font)
  270.         XFreeFont(x11_display, vw->vw_Font);
  271.     vw->vw_Font = font;
  272.     vw->vw_FontX = XTextWidth(font, "M", 1);
  273.     vw->vw_FontY = vw->vw_Font->ascent + vw->vw_Font->descent;
  274.     if(vw->vw_Window)
  275.     {
  276.         int w, h;
  277.         w = vw->vw_MaxX * vw->vw_FontX;
  278.         h = ((vw->vw_MaxY + 1) * vw->vw_FontY) + 3;
  279.         XSetFont(x11_display, vw->vw_WindowSys.ws_TextFontGC, font->fid);
  280.         XSetFont(x11_display, vw->vw_WindowSys.ws_BlkFontGC, font->fid);
  281.         sys_update_dimensions(vw);
  282.         size_hints.width = w;
  283.         size_hints.height = h;
  284.         size_hints.base_width = 0;
  285.         size_hints.base_height = vw->vw_FontY + 3;
  286.         size_hints.width_inc = vw->vw_FontX;
  287.         size_hints.height_inc = vw->vw_FontY;
  288.         size_hints.min_width = size_hints.base_width + size_hints.width_inc;
  289.         size_hints.min_height = size_hints.base_height + size_hints.height_inc;
  290.         size_hints.flags = PResizeInc | PMinSize | PBaseSize;
  291.         XSetWMNormalHints(x11_display, vw->vw_Window, &size_hints);
  292.         XResizeWindow(x11_display, vw->vw_Window, w, h);
  293. #if 0
  294.         vw->vw_DeferRefresh++;
  295. #endif
  296.     }
  297.     return(TRUE);
  298.     }
  299.     return(FALSE);
  300. }
  301.  
  302. void
  303. sys_unset_font(VW *vw)
  304. {
  305.     if(vw->vw_Font)
  306.     {
  307.     XFreeFont(x11_display, vw->vw_Font);
  308.     vw->vw_Font = NULL;
  309.     }
  310. }
  311.  
  312. _PR VALUE cmd_set_font(VALUE fontname, VALUE vw);
  313. DEFUN_INT("set-font", cmd_set_font, subr_set_font, (VALUE fontname, VALUE vw), V_Subr2, DOC_set_font, "sFont name: ") /*
  314. ::doc:set_font::
  315. set-font FONT-NAME [WINDOW]
  316.  
  317. FONT-NAME specifies the font to use in WINDOW (or the active one).
  318. Under X11 FONT-NAME is a standard font description, under AmigaDOS it is the
  319. name of the font followed by a dash and then the point size to use (for
  320. example "topaz.font-8" to get an 8-point topaz font).
  321. ::end:: */
  322. {
  323.     VALUE oldfont;
  324.     DECLARE1(fontname, STRINGP);
  325.     if(!WINDOWP(vw))
  326.     vw = VAL(curr_vw);
  327.     oldfont = VWIN(vw)->vw_FontName;
  328.     VWIN(vw)->vw_FontName = fontname;
  329.     if(sys_set_font(VWIN(vw)))
  330.     {
  331.     VWIN(vw)->vw_Flags |= VWFF_FORCE_REFRESH;
  332. #if 0
  333.     VWIN(vw)->vw_DeferRefresh++;
  334. #endif
  335.     return(sym_t);
  336.     }
  337.     else
  338.     {
  339.     cmd_signal(sym_error, list_2(MKSTR("Can't open font"), fontname));
  340.     VWIN(vw)->vw_FontName = oldfont;
  341.     return(NULL);
  342.     }
  343. }
  344.  
  345. void
  346. sys_reset_sleep_titles(TX *tx)
  347. {
  348. }
  349.  
  350. _PR VALUE cmd_screen_width(void);
  351. DEFUN("screen-width", cmd_screen_width, subr_screen_width, (void), V_Subr0, DOC_screen_width) /*
  352. ::doc:screen_width::
  353. screen-width
  354.  
  355. Returns the width of the root window or screen in pixels.
  356. ::end:: */
  357. {
  358.     Window root;
  359.     int dummy1;
  360.     unsigned int dummy2;
  361.     int val;
  362.     if(XGetGeometry(x11_display, DefaultRootWindow(x11_display),
  363.             &root, &dummy1, &dummy1,
  364.             (unsigned int *)&val, &dummy2,
  365.             &dummy2, &dummy2))
  366.     return(make_number(val));
  367.     return(NULL);
  368. }
  369.  
  370. _PR VALUE cmd_screen_height(void);
  371. DEFUN("screen-height", cmd_screen_height, subr_screen_height, (void), V_Subr0, DOC_screen_height) /*
  372. ::doc:screen_height::
  373. screen-height
  374.  
  375. Returns the height of the root window or screen in pixels.
  376. ::end:: */
  377. {
  378.     Window root;
  379.     int dummy1;
  380.     unsigned int dummy2;
  381.     int val;
  382.     if(XGetGeometry(x11_display, DefaultRootWindow(x11_display),
  383.             &root, &dummy1, &dummy1,
  384.             &dummy2, (unsigned int *)&val,
  385.             &dummy2, &dummy2))
  386.     return(make_number(val));
  387.     return(NULL);
  388. }
  389.  
  390. _PR VALUE cmd_window_left_edge(void);
  391. DEFUN("window-left-edge", cmd_window_left_edge, subr_window_left_edge, (void), V_Subr0, DOC_window_left_edge) /*
  392. ::doc:window_left_edge::
  393. window-left-edge
  394.  
  395. Returns the x position of the current window relative to the origin of the
  396. root window or screen.
  397. ::end:: */
  398. {
  399.     Window tmp;
  400.     int x, y;
  401.     if(XTranslateCoordinates(x11_display, curr_vw->vw_Window,
  402.                  DefaultRootWindow(x11_display), 0, 0, &x, &y, &tmp))
  403.     return(make_number(x));
  404.     return(NULL);
  405. }
  406.  
  407. _PR VALUE cmd_window_top_edge(void);
  408. DEFUN("window-top-edge", cmd_window_top_edge, subr_window_top_edge, (void), V_Subr0, DOC_window_top_edge) /*
  409. ::doc:window_top_edge::
  410. window-top-edge
  411.  
  412. Returns the y position of the current window relative to the origin of the
  413. root window or screen.
  414. ::end:: */
  415. {
  416.     Window tmp;
  417.     int x, y;
  418.     if(XTranslateCoordinates(x11_display, curr_vw->vw_Window,
  419.                  DefaultRootWindow(x11_display), 0, 0, &x, &y, &tmp))
  420.     return(make_number(y));
  421.     return(NULL);
  422. }
  423.  
  424. _PR VALUE cmd_window_width(void);
  425. DEFUN("window-width", cmd_window_width, subr_window_width, (void), V_Subr0, DOC_window_width) /*
  426. ::doc:window_width::
  427. window-width
  428.  
  429. Returns the width, in pixels, of the current window.
  430. ::end:: */
  431. {
  432.     Window root;
  433.     int dummy1;
  434.     unsigned int dummy2;
  435.     int val;
  436.     if(XGetGeometry(x11_display, curr_vw->vw_Window,
  437.             &root, &dummy1, &dummy1,
  438.             (unsigned int *)&val, &dummy2,
  439.             &dummy2, &dummy2))
  440.     return(make_number(val));
  441.     return(NULL);
  442. }
  443.  
  444. _PR VALUE cmd_window_height(void);
  445. DEFUN("window-height", cmd_window_height, subr_window_height, (void), V_Subr0, DOC_window_height) /*
  446. ::doc:window_height::
  447. window-height
  448.  
  449. Returns the height, in pixels, of the current window.
  450. ::end:: */
  451. {
  452.     Window root;
  453.     int dummy1;
  454.     unsigned int dummy2;
  455.     int val;
  456.     if(XGetGeometry(x11_display, curr_vw->vw_Window,
  457.             &root, &dummy1, &dummy1,
  458.             &dummy2, (unsigned int *)&val,
  459.             &dummy2, &dummy2))
  460.     return(make_number(val));
  461.     return(NULL);
  462. }
  463.  
  464. _PR VALUE cmd_window_bar_height(void);
  465. DEFUN("window-bar-height", cmd_window_bar_height, subr_window_bar_height, (void), V_Subr0, DOC_window_bar_height) /*
  466. ::doc:window_bar_height::
  467. window-bar-height
  468.  
  469. On an Amiga returns the number of pixels high the title bar of the window
  470. is. This is 0 in X11.
  471. ::end:: */
  472. {
  473.     return(make_number(0));
  474. }
  475.  
  476. bool
  477. sys_get_mouse_pos(POS *pos, VW *vw)
  478. {
  479.     Window tmpw;
  480.     int tmp;
  481.     int x, y;
  482.     if(XQueryPointer(x11_display, vw->vw_Window, &tmpw, &tmpw, &tmp, &tmp, &x, &y, &tmp))
  483.     {
  484.     x = (x - vw->vw_XStartPix) / vw->vw_FontX;
  485.     y = (y - vw->vw_YStartPix) / vw->vw_FontY;
  486.     if((x < 0) || (y < 0) || (x >= vw->vw_MaxX) || (y >= vw->vw_MaxY))
  487.         return(FALSE);
  488.     pos->pos_Col = x + vw->vw_StartCol;
  489.     pos->pos_Line = y + vw->vw_StartLine;
  490.     if(pos->pos_Col < 0)
  491.         pos->pos_Col = 0;
  492.     if(pos->pos_Line < 0)
  493.         pos->pos_Line = 0;
  494.     if(pos->pos_Line >= vw->vw_Tx->tx_NumLines)
  495.         pos->pos_Line = vw->vw_Tx->tx_NumLines - 1;
  496.        pos->pos_Col = char_col(vw->vw_Tx, x + vw->vw_StartCol, pos->pos_Line);
  497.        return(TRUE);
  498.     }
  499.     return(FALSE);
  500. }
  501.  
  502. _PR VALUE cmd_flush_output(void);
  503. DEFUN("flush-output", cmd_flush_output, subr_flush_output, (void), V_Subr0, DOC_flush_output) /*
  504. ::doc:flush_output::
  505. flush-output
  506.  
  507. Forces any cached window output to be drawn. This is usually unnecessary.
  508. ::end:: */
  509. {
  510.     XFlush(x11_display);
  511.     return(sym_t);
  512. }
  513.  
  514. void
  515. sys_windows_init(void)
  516. {
  517.     ADD_SUBR(subr_set_font);
  518.     ADD_SUBR(subr_screen_width);
  519.     ADD_SUBR(subr_screen_height);
  520.     ADD_SUBR(subr_window_left_edge);
  521.     ADD_SUBR(subr_window_top_edge);
  522.     ADD_SUBR(subr_window_width);
  523.     ADD_SUBR(subr_window_height);
  524.     ADD_SUBR(subr_window_bar_height);
  525.     ADD_SUBR(subr_flush_output);
  526. }
  527.